package com.xingchi.tornado.security.service;

import com.xingchi.tornado.basic.BaseEnum;
import com.xingchi.tornado.security.enums.LoginSourceEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;

/**
 * 登录来源管理器接口，建议在统一的配置类或加载类中添加登录来源，方便管理和维护
 *
 * @author xiaoya
 * @date 2025/7/21 17:02
 */
@Slf4j
public final class LoginSourceManager {

    public static final List<LoginSourceService> LOGIN_SOURCE_SERVICE_LIST;

    public static BiFunction<String, Integer, LoginSourceService> loginSourceFactory = LoginSourceService::build;

    static {
        LOGIN_SOURCE_SERVICE_LIST = new ArrayList<>();
        LoginSourceEnum[] values = LoginSourceEnum.values();
        for (LoginSourceEnum value : values) {
            LOGIN_SOURCE_SERVICE_LIST.add(loginSourceFactory.apply(value.getDesc(), value.getCode()));
        }
    }

    private LoginSourceManager() {
        throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
    }

    public static LoginSourceService getLoginSourceService(Integer code) {
        for (LoginSourceService loginSourceService : LOGIN_SOURCE_SERVICE_LIST) {
            if (loginSourceService.supports(code)) {
                return loginSourceService;
            }
        }
        log.warn("登录来源不支持，来源：{}", code);
        throw new IllegalArgumentException("登录来源不正确");
    }

    public static LoginSourceService getInstance(Integer code) {
        return getLoginSourceService(code);
    }

    public static boolean add(BaseEnum baseEnum) {
        LoginSourceService apply = loginSourceFactory.apply(baseEnum.getDesc(), baseEnum.getCode());
        return add(apply);
    }

    public static boolean add(String name, Integer code) {
        LoginSourceService apply = loginSourceFactory.apply(name, code);
        return add(apply);
    }

    private static boolean add(LoginSourceService apply) {
        synchronized (LOGIN_SOURCE_SERVICE_LIST) {
            Integer code = apply.getCode();
            boolean exists = LOGIN_SOURCE_SERVICE_LIST.stream().anyMatch(loginSourceService -> loginSourceService.supports(code));
            if (exists) {
                log.error("登录来源已存在，来源：{}", code);
                throw new IllegalArgumentException(String.format("登录来源已存在 %s", code));
            }
            return LOGIN_SOURCE_SERVICE_LIST.add(apply);
        }
    }

    public static boolean remove(Integer code) {
        synchronized (LOGIN_SOURCE_SERVICE_LIST) {
            return LOGIN_SOURCE_SERVICE_LIST.removeIf(loginSourceService -> loginSourceService.supports(code));
        }
    }

    public static void prettyPrint() {
        StringBuilder sb = new StringBuilder();
        sb.append("\n");
        sb.append(StringUtils.repeat("=", 50)).append("\n");
        sb.append("\t\t\t登录来源，共计 ").append(LOGIN_SOURCE_SERVICE_LIST.size()).append(" 种\n");
        LOGIN_SOURCE_SERVICE_LIST.forEach(loginSourceService ->  sb.append("\t\t\t\t").append(loginSourceService.getName()).append(":").append(loginSourceService.getCode()).append("\n"));
        sb.append(StringUtils.repeat("=", 50)).append("\n");
        log.info(sb.toString());
    }

}
